<?php

/*
This class works with the Mantis Issue tracker to check and record user-authentication. A User must be a Mantis Issue Tracker user
to use Google Refine. If not, the Reverse Proxy Server won't pass on HTTP requests to Google Refine.

Main Functions:
(1) Check if current session is authorized (an authorization file needs to be associated with the current session-id )
(2) Make an authorization file, based on data POSTed from the Mantis RefineHistory Plugin
(3) Clean-up old session authorization files.

*/

class MantisAuthorize{
	
	public $authorizedSession; //current session is authorized / true or false.
	public $editIssueResolved; //is the edit issue resolved?
	public $editIssue; //id for the edit issue
	
	public $authorization; // SH1 hashed prefix and session id together. hashed so authorization key not revealed
	public $message; //array of authorization data sent by the issue tracker
	public $sessionID; //session ID OK'd for access to Google Refine
	public $savedAuth;
	public $publicBaseURL;
	
	const authHashPrefix = "your hash salt here"; //prefix appended to session id to authorize user for Google Refine.
	const session_auth_directory = "./sessions/"; //directory for saving authorized sessions
	const project_log_directory = "./project-logs/"; //directory for JSON files associating Issue tracker username and project ID with Google Refine projects
	const auth_file_lifetime = 86400; //life time of authorization file, 86400 = 1 day
	
	
	function initialize(){
		
		$this->authorization = false;
		$this->message = false;
		$this->sessionID = false;
		$this->savedAuth = false;
	}
	
	function checkAuthorization(){
		//checks if the current session ID is authorized. If a session authorization file exists (with the right name), it's authorized.
		$this->editIssueResolved = false;
		$this->editIssue = false;
		$file = $this->sessionID.".json";
		$filename = self::session_auth_directory.$file;

		if(file_exists($filename)) {
			$this->authorizedSession = true;
			$this->logProjectAuthorization($filename);
			$output = true;
		}
		else{
			$this->authorizedSession = false;
			$output = false;
		}
		
		return $output;
	}
	
	
	
	function logProjectAuthorization($filename){
		//saves the relationship between session ID, the issue tracker user ID, and the issue tracker Project ID with the 	
		//Google Refine Project ID.
		$ProjectURIpart =  "/project?project=";
		
		if(stristr($_SERVER["REQUEST_URI"], $ProjectURIpart)){
			
			//echo "found!".$ProjectURIpart;
			$GRprojectID = $_GET["project"];
			$OldAuthorizationMessage = $this->read_parse_json($filename);
			$userID = $OldAuthorizationMessage["userID"];
			
			$grProjectFile =  self::project_log_directory.$GRprojectID.".json";
			$GRprojectAuth = false;
			if(file_exists($grProjectFile)) {
				$GRprojectAuth = $this->read_parse_json($grProjectFile);
				$this->editIssueResolved = $GRprojectAuth["editResolved"];
				if(isset($GRprojectAuth["editID"])){
					$this->editIssue = $GRprojectAuth["editID"];
				}
			}
			
			if(!$GRprojectAuth){
				$GRprojectAuth = array();
				$GRprojectAuth["GRprojectID"] = $GRprojectID;
				$GRprojectAuth["users"] = array();
				$GRprojectAuth["editResolved"] = false;
				$this->editIssueResolved = false;
			}
			
			if(!array_key_exists($userName, $GRprojectAuth["users"])){
				
				if(isset($_COOKIE['MANTIS_PROJECT_COOKIE'])){
					$OldAuthorizationMessage["actIssueProject"] = $_COOKIE['MANTIS_PROJECT_COOKIE'];
				}
				
				$GRprojectAuth["users"][$userID] = $OldAuthorizationMessage; //associate the orginal authorization message
				
				$json = json_encode($GRprojectAuth, true);
				$fp = fopen($grProjectFile, 'w');
				fwrite($fp, iconv("ISO-8859-7","UTF-8",$json));
				fclose($fp);
			}
			
		}
		
	}
	
	function updateProjectEditIssueState(){
		
		if($_SERVER['REQUEST_METHOD'] == 'POST'){
			$editID = false;
			$editResolved = "not indicated";
			
			$possAuthorization = $this->getAuthorizationHeader(); //look for authorization in the message header
			if(!$this->authorization && isset($_POST["authorization"])){
				$this->authorization = $_POST["authorization"];
			}
			
			if(isset($_POST["editID"])){
				$editID = $_POST["editID"];
			}
			
			if(isset($_POST["editResolved"])){
				$editResolved = $_POST["editResolved"];
			}
			
			if(isset($_POST["project"])){
				$GRprojectID = $_POST["project"];
			}
			
			$requiredAuthorization = sha1(self::authHashPrefix.$GRprojectID);
			if($requiredAuthorization == $this->authorization){
				//authorization OK! :)
				if($editID != false && $editResolved != "not indicated"){
					
					$this->editIssue = $editID;
					$this->editIssueResolved = $editResolved;
					
					$grProjectFile =  self::project_log_directory.$GRprojectID.".json";
					$GRprojectAuth = $this->read_parse_json($grProjectFile);
					$GRprojectAuth["editID"] = $editID;
					$GRprojectAuth["editResolved"] = $editResolved;
					
					$json = json_encode($GRprojectAuth, true);
					$fp = fopen($grProjectFile, 'w');
					fwrite($fp, iconv("ISO-8859-7","UTF-8",$json));
					fclose($fp);
					
				}

			}
			
		}
	}
	
	
	
	function projectUsers(){
		
		$authorization = $_GET["auth"];
		$GRprojectID = $_GET["grProject"];
		$GRprojectAuth = false;
		if(sha1(self::authHashPrefix.$GRprojectID) == $authorization){
			//authorized to get project user data
			$grProjectFile =  self::project_log_directory.$GRprojectID.".json";
			if(file_exists($grProjectFile)) {
				$GRprojectAuth = $this->read_parse_json($grProjectFile);
			}
			$headerData = 'Content-Type: application/json; charset=utf8';
		}
		else{
			$headerData = 'HTTP/1.1 403 Forbidden';
		}
		
		header($headerData);
		echo json_encode($GRprojectAuth, true);
	}
	
	
	
	
	
	function checkMessage(){
		//check authorization token message POSTed by the Data Refine Mantis Plugin	
		
		if($_SERVER['REQUEST_METHOD'] == 'POST'){
			//message has to be post
			$possAuthorization = $this->getAuthorizationHeader(); //look for authorization in the message header
			if(!$this->authorization && isset($_POST["authorization"])){
				$this->authorization = $_POST["authorization"];
			}
				
			if(isset($_POST["sessionID"])){
				$this->sessionID = $_POST["sessionID"];
			}
		}
		
		
		if($this->authorization != false && $this->sessionID != false){
			//the authorization message has the right form
			//now check to see if the authorization token is correct
			$message = array();
			foreach($_POST as $key => $value){
				$message[$key] = $value;
			}
			$this->message = $message;
			
			$requiredAuthorization = sha1(self::authHashPrefix.$this->sessionID);
			if($requiredAuthorization == $this->authorization){
				//yes! the authorization is correct, make a new session authorization file
				$this->saveAuthorization();
			}
			else{
				//don't do anything.
			}
		}
		
		$this->cleanOldAuthorizations(); //do a little clean-up
	}
	
	function saveAuthorization(){
		//save the little JSON data into the appropriate directory. This creates a session authorization file
		
		$sessionID = $this->sessionID;
		$json = json_encode($this->message, true);
		
		$fp = fopen(self::session_auth_directory.$sessionID.'.json', 'w');
		fwrite($fp, iconv("ISO-8859-7","UTF-8",$json));
                fclose($fp);
		$this->savedAuth = true;
	}
	
	
	function cleanOldAuthorizations(){
		//remove old authorization files that are older than a certain time.
		
		$path = self::session_auth_directory;
		if ($handle = opendir($path)) {
			while (false !== ($file = readdir($handle))) {
				if ((time()-filectime($path.$file)) >= self::auth_file_lifetime) {  
					if (preg_match('/\.json$/i', $file)) {
					   unlink($path.$file);
					}
				}
			}
		}
		
	}
	
	
	
	function getAuthorizationHeader(){
		//check for authorization in the HTTP header
		$output = false;
		$headers = apache_request_headers();
		foreach ($headers as $header => $value) {
		    if(stristr($header, "authorization")){
			$this->authorization = $value;
			$output = $value;
		    }
		}
		
		return $output;
	}
	
	
	public function read_parse_json($filename){
		$output = false;
		
		$rHandle = fopen($filename, 'r');
		if (!$rHandle){
		    //nothing
		}
		else{
		    
		    $sData = '';
		    while(!feof($rHandle))
			$sData .= fread($rHandle, filesize($filename));
		    fclose($rHandle);
		    unset($rHandle);
		    
		    $output = json_decode($sData, true); //convert JSON string to array
		}

		return $output;
	}//end function
	
	
}
?>